/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ddnsserver;

/**
 *
 * @author Do Viet Trung
 */

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.tree.*;


public class DNSConvert implements ActionListener, TreeSelectionListener {
    public static boolean RIGHT_TO_LEFT = false;
    private String filePathNameServer,
            filePathResultOutput,
            filePathForwardZone,
            filePathReverseZone;
    private NameServer ns;
    private Server server;
    private Vector <DomainInfo> DomainInformation;
    private static Vector <Domain> TopDomains;
    Vector<String> reverseZone;
    Vector<String> forwardZone;
    private Container pane;
    public static JFrame frame;
    private JPanel panePageStart,
            paneCenter,
            panePageEnd,
            paneBtnCenter,
            paneLineStart,
            paneLineEnd,
            pane1,
            pane2,
            pane3,
            pane4;
    private JTable table;
    private DefaultTableModel model;
    private JTextField textNameServer,
            fileoutput;
    private JList listPreview;
    private DefaultListModel listModel;
    private JTextArea textPreview;
    private JLabel label1,
            label2,
            label3,
            label4,
            label5,
            label6;
    private JButton btnConfig,
            btnChoseFileInput,
            btnChoseFileOutput,
            btnCheck,
            btnConvert,
            btnCancel;
    private JFileChooser fci,
                  fco;
    private JTree tree;
    private JScrollPane scrollPane;
    private DefaultMutableTreeNode top,
            forward,
            reverse;
    private JComboBox comboTypeServer,
            comboReverseZone;
    private JCheckBox checkBox;
    private GridLayout gridLayout1 = new GridLayout(3, 1);
    private GridLayout gridLayout2 = new GridLayout(1, 2);
    private BorderLayout border1 = new BorderLayout();
    private GridBagLayout gridBagLayout1 = new GridBagLayout();
    private GridBagConstraints gridBagCons = new GridBagConstraints();
    private FlowLayout flowLayout1 = new FlowLayout();
    private boolean isChecked;

   
    private JPanel createPageStart() {
        panePageStart = new JPanel(gridLayout1);
        pane1 = new JPanel(gridBagLayout1);
        label2 = new JLabel("Folder input:    ");

        textNameServer = new JTextField();
        textNameServer.setPreferredSize(new Dimension(500, 26));
        textNameServer.setEditable(false);

        btnChoseFileInput = new JButton("...");
        btnChoseFileInput.setActionCommand("btnChoseFileInput");
        btnChoseFileInput.addActionListener(this);

        pane1.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        gridBagCons.gridx = 0;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        pane1.add(label2,gridBagCons);

        gridBagCons.gridx = 1;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 10;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane1.add(textNameServer, gridBagCons);

        gridBagCons.gridx = 2;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 0;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane1.add(btnChoseFileInput,gridBagCons);

//        /////////
        pane4 = new JPanel(gridBagLayout1);
        label6 = new JLabel("Folder output:  ");
        fileoutput = new JTextField();
        fileoutput.setPreferredSize(new Dimension(500, 26));
        fileoutput.setEditable(false);

        btnChoseFileOutput = new JButton("...");
        btnChoseFileOutput.setActionCommand("btnChoseFileOutput");
        btnChoseFileOutput.addActionListener(this);

        pane4.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        gridBagCons.gridx = 0;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        pane4.add(label6,gridBagCons);

        gridBagCons.gridx = 1;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 10;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane4.add(fileoutput, gridBagCons);

        gridBagCons.gridx = 2;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 0;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane4.add(btnChoseFileOutput,gridBagCons);

        ////////
        pane2 = new JPanel(gridBagLayout1);
        label3 = new JLabel("Type Server:    ");
        label4 = new JLabel(" ");
        Object b[] = new Object[2];
        b[0] = "Primary DNS Server";
        b[1] = "Secondary DNS Server";
        comboTypeServer = new JComboBox(b);
        comboTypeServer.setPreferredSize(new Dimension(470, 26));
        btnCheck = new JButton("Check");
        btnCheck.setActionCommand("btnCheck");
        btnCheck.addActionListener(this);

        pane2.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        gridBagCons.gridx = 0;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        pane2.add(label3,gridBagCons);

        gridBagCons.gridx = 1;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 10;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane2.add(comboTypeServer, gridBagCons);

        gridBagCons.gridx = 2;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 0;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane2.add(label4, gridBagCons);

        gridBagCons.gridx = 3;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 0;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.weightx = 0;
        pane2.add(btnCheck,gridBagCons);
        ///

        panePageStart.add(pane1);
        panePageStart.add(pane4);
        panePageStart.add(pane2);

        return panePageStart;
    }
   
    private JPanel createPageEnd() {
        panePageEnd = new JPanel(gridBagLayout1);
        panePageEnd.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 2) );

        btnConvert = new JButton("Convert");
        btnConvert.setActionCommand("btnConvert");
        btnConvert.addActionListener(this);

        btnCancel = new JButton("Quit");
        btnCancel.setActionCommand("btnCancel");
        btnCancel.addActionListener(this);

        label5 = new JLabel("         ");
        gridBagCons.gridx = 0;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        gridBagCons.gridwidth = 1;
        panePageEnd.add(btnConvert, gridBagCons);

        gridBagCons.gridx = 1;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        panePageEnd.add(label5, gridBagCons);

        gridBagCons.gridx = 2;
        gridBagCons.gridy = 0;
        gridBagCons.weighty = 2;
        gridBagCons.gridheight = 2;
        gridBagCons.insets = new Insets(5,0,0,0);
        panePageEnd.add(btnCancel, gridBagCons);

        return panePageEnd;
   }
    
    private JPanel createLineStart() {
       paneLineStart = new JPanel();
       Object t[] =new Object[1];
       t[0] = "SERVER";

       top = new DefaultMutableTreeNode("SERVER");
        //createNodes(top);

        //Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);

        //Listen for when the selection changes.
        tree.addTreeSelectionListener(this);
        
        forward = new DefaultMutableTreeNode("Forward Lookup Zone");
        top.add(forward);
        reverse = new DefaultMutableTreeNode("Reverse Lookup Zone");
        top.add(reverse);

        tree.setPreferredSize(new Dimension(230, 410));
        tree.setAutoscrolls(true);
        JScrollPane srollTree = new JScrollPane(tree);
        paneLineStart.add(srollTree);

        return paneLineStart;
    }
   
    private JPanel createLineEnd() {
        paneLineEnd = new JPanel(new BorderLayout());
        paneLineEnd.setOpaque(true);

        textPreview = new JTextArea(5,20);
        textPreview.setText("Preview:");
        textPreview.setAutoscrolls(true);
        textPreview.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
        textPreview.setEditable(false);
        textPreview.setPreferredSize(new Dimension(200, 400));
        Font f = new Font("Time New Roman", 0, 12);
        textPreview.setFont(f);
        textPreview.setLineWrap(true);
        textPreview.setWrapStyleWord(true);
        scrollPane = new JScrollPane(textPreview);
        paneLineEnd.add(scrollPane,BorderLayout.CENTER);

        return paneLineEnd;
    }
    
    private JPanel createCenter() {
        paneCenter = new JPanel(border1);
        String[] columnNames = {"No. ",
                    "Forward Lookup Zone",
                    "Reverse Lookup Zone",
                    };
        Object[][] data = {{"",  "",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}
                            ,{"","",""},{"","",""},{"","",""},{"","",""},{"","",""}};
        label1 = new JLabel("List Domains:");
        btnConfig = new JButton("Configure");
        model = new DefaultTableModel(data,columnNames);

        // tạo table k cho chỉnh sửa thông tin trên cell
        table = new JTable(model) {
            @Override
            public boolean isCellEditable(int rowIndex, int colIndex) {
                if (colIndex % 2 == 0) {
                    return true;
                }
                return false;
            }
        };
        
        table.setPreferredSize(new Dimension(600, 600));
        table.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 3));
        JScrollPane treeScrollPane = new JScrollPane(table);
        //table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setFillsViewportHeight(true);
        table.setPreferredScrollableViewportSize(new Dimension(300, 300));
        table.setRowHeight(20);

        btnConfig.setActionCommand("btnConfigure");
        btnConfig.addActionListener(this);
        btnConfig.setEnabled(false);
        ///
        TableColumn sportColumn = table.getColumnModel().getColumn(2);
        
        Object b[] = new Object[1];
         b[0] = " ";
       
        comboReverseZone = new JComboBox(b);
        checkBox = new JCheckBox();
        checkBox.setSelected(true);

        sportColumn.setCellEditor(new DefaultCellEditor(comboReverseZone));
       
        ////
        TableColumn column = null;

        for (int i = 0; i <3; i++) {
            column = table.getColumnModel().getColumn(i);

            if (i == 0) {
                column.setPreferredWidth(25); //third column is bigger
            } else {
                column.setPreferredWidth(350);
            }
        }

        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        flowLayout1.setAlignment(2);
        paneBtnCenter = new JPanel(flowLayout1);
        paneBtnCenter.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

        paneBtnCenter.add(btnConfig);
        paneCenter.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1) );
        //        list = new JList();
        //        list.setPreferredSize(new Dimension(400, 300));
        paneCenter.add(label1, BorderLayout.PAGE_START);
        // paneCenter.add(table, BorderLayout.CENTER);
        paneCenter.add(treeScrollPane, BorderLayout.CENTER);
        paneCenter.add(paneBtnCenter,BorderLayout.PAGE_END);

        return paneCenter;
    }

    public Container addComponentsToPane() {
        pane = frame.getContentPane();

        if (!(pane.getLayout() instanceof BorderLayout)) {
            pane.add(new JLabel("Container doesn't use BorderLayout!"));
            return null;
        }

        if (RIGHT_TO_LEFT) {
            pane.setComponentOrientation(
                java.awt.ComponentOrientation.LEFT_TO_RIGHT);
        }

        pane.add(createPageStart(), BorderLayout.PAGE_START);
        pane.add(createCenter(), BorderLayout.CENTER);
        pane.add(createPageEnd(), BorderLayout.PAGE_END);
        pane.add(createLineStart(), BorderLayout.LINE_START);
        pane.add(createLineEnd(), BorderLayout.LINE_END);

        return pane;
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getActionCommand().equals("btnChoseFileInput")) {
            fci = new JFileChooser();
            fci.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int returnVal = fci.showOpenDialog(pane);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fci.getSelectedFile();

                try {
                    filePathNameServer = file.getCanonicalPath();
                    filePathForwardZone = filePathNameServer + "\\" + "Forward Lookup Zone";
                    filePathReverseZone = filePathNameServer + "\\" + "Reverse Lookup Zone";
                    textNameServer.setText(filePathNameServer);
                    fci.setCurrentDirectory(new File(filePathNameServer));
                    textNameServer.setEditable(true);
                    btnCheck.setEnabled(true);
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(paneCenter, ex.getMessage(),"Error",2);
                }
            } 
        }

        if(e.getActionCommand().equals("btnChoseFileOutput")) {
            fco = new JFileChooser();
            fco.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

            int returnVal = fco.showOpenDialog(pane);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fco.getSelectedFile();

                try {
                    filePathResultOutput = file.getCanonicalPath();
                    fileoutput.setEditable(true);
                    btnCheck.setEnabled(true);
                    btnConfig.setEnabled(false);
                    fileoutput.setText(filePathResultOutput);
                    fco.setCurrentDirectory(file);
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(paneCenter, ex.getMessage(),"Error",1);
                }
            }
        }

        if(e.getActionCommand().equals("btnCheck")) {
            if(filePathNameServer != null) {
                try {
                    //server
                    NameServer.TYPE_SERVER t = NameServer.TYPE_SERVER.PRIMARY;
                    
                    if (comboTypeServer.getSelectedItem().equals("Secondary DNS Server")) {
                        t = NameServer.TYPE_SERVER.SECONDARY;
                    }
                    
                    String server_name = FileAndFolder.getLastLevel(filePathNameServer);
                    server = new Server(server_name,filePathNameServer,t);
                    //domain info
                    textNameServer.setEditable(false);
                    btnCheck.setEnabled(false);
                    btnConfig.setEnabled(true);
                    forwardZone = new Vector<String>();
                    reverseZone = new Vector<String>();

                    forwardZone = FileAndFolder.list(filePathForwardZone);
                    reverseZone = FileAndFolder.list(filePathReverseZone);

                    searchDomains (
                            forwardZone,
                            reverseZone,
                            filePathForwardZone,
                            filePathReverseZone);

                    reverseZone = JProcess.removeCharBegin(reverseZone, 0);
                    reverseZone.add("none");
                    reverseZone.add(" ");

                    setComboBoxData(comboReverseZone,reverseZone);
                    setTableData();
                    //load all domain and subdomain
                    loadDomains();

                    this.isChecked = true;
                } catch(Exception ex) {
                    JOptionPane.showMessageDialog(paneCenter, ex.getMessage(),"Error",0);
                }
            } else {
                JOptionPane.showMessageDialog(paneCenter, "Please input Folder of DNS file configuration. ","Error",2);
            }
        }

        if(e.getActionCommand().equals("btnConfigure")) {
            int idx = table.getSelectedRow();
            int len = this.DomainInformation.size();
            
            if (idx >= 0 && idx < len) {
                // Tim kiem de quy host
                String host = (String)this.table.getValueAt(idx, 1);
                Domain domain = findDomain (TopDomains, host);

                ConfigurationDomain conf = new ConfigurationDomain();
                conf.createAndShowGUI(domain, idx);
            } else {
                JOptionPane.showMessageDialog(pane, "Choose domain first!");
            }
        }


        if(e.getActionCommand().equals("btnConvert")) {
            // Kiểm tra

            try {
                if (!this.filePathNameServer.equals("") && this.isChecked) {
                    // Kiểm tra xem đã cấu hình các domain hay chưa?

                    // Populate your panel components here.
        //            JPanel panel = new JPanel(new GridBagLayout ());
                    JPanel panel = new JPanel(new GridLayout (8,2));

                    JTextField txtDirectory = new JTextField ("/var/named");
                    JTextField txtDumpFile = new JTextField("/var/named/cache_dump.db");
                    JTextField txtStatisticsFile =
                            new JTextField ("/var/named/named_stats.txt");
                    JTextField txtMemstatisticsFile =
                            new JTextField ("/var/named/named_mem_stats.txt");
                    JTextField txtForwarder = new JTextField ();
                    JTextField txtListenOn = new JTextField();
                    String []choose = {"yes", "no"};
                    JComboBox cbxNotify = new JComboBox(choose);
                    JTextField txtInclude = new JTextField ("/etc/named.rfc1912.zones");

                    panel.add (new JLabel ("Listen on port 53:"));
                    panel.add (txtListenOn);
                    panel.add (new JLabel ("Directory: "));
                    panel.add (txtDirectory);
                    panel.add (new JLabel ("dump-file:"));
                    panel.add (txtDumpFile);
                    panel.add (new JLabel ("statistic-file:"));
                    panel.add (txtStatisticsFile);
                    panel.add (new JLabel ("memstatistic-file:"));
                    panel.add (txtMemstatisticsFile);
                    panel.add (new JLabel ("forwarders:"));
                    panel.add (txtForwarder);
                    panel.add (new JLabel ("notify:"));
                    panel.add (cbxNotify);
                    panel.add (new JLabel ("include:"));
                    panel.add (txtInclude);

                    panel.setPreferredSize(new Dimension (480, 225));
                    int ret = JOptionPane.showConfirmDialog(
                            frame,
                            panel,
                            "Configuration named file",
                            JOptionPane.YES_NO_OPTION);

                    if ( ret == JOptionPane.YES_OPTION ) {
                      // Read component values.
                        String interfaces = txtListenOn.getText();
                        String directory = txtDirectory.getText();
                        String dumpFile = txtDumpFile.getText();
                        String statisticsFile = txtStatisticsFile.getText();
                        String memstatisticsFile = txtMemstatisticsFile.getText();
                        String forwarders = txtForwarder.getText();
                        String notify = cbxNotify.getSelectedItem().toString();
                        String includes = txtInclude.getText();

                        writeNamedFile (
                                interfaces,
                                directory,
                                dumpFile,
                                statisticsFile,
                                memstatisticsFile,
                                forwarders,
                                notify,
                                includes);
                    }
                } else {
                    JOptionPane.showMessageDialog(this.pane, "Please click button \"Check\"");
                }

            } catch (Exception ex) {
                System.err.println (ex.getMessage());

                JOptionPane.showMessageDialog(
                        this.pane,
                        "Please choose folder input and click button \"Check\"");
            }
        }

        if(e.getActionCommand().equals("btnCancel")) {
            clearTable();
            
            DNSConvert.frame.setVisible(false);
        }
    }

    public void writeNamedFile (
            String interfaces,
            String directory,
            String dumpFile,
            String statisticFile,
            String memstatisticFile,
            String forwarders,
            String notify,
            String includes ) {

        try {
            if (dectectOS().equals("Windows")) {
                // create named file
                FileWriter fstream = new FileWriter("named.conf");
                BufferedWriter out = new BufferedWriter(fstream);

                // write file
                out.write("options {");
                out.write("\n");
                out.write("\tlisten-on port 53 { " + interfaces + "; }");
                out.write("\n");
                out.write("\tdirectory\t\"" + directory + "\";");
                out.write("\n");
                out.write("\tdump-file\t\"" + dumpFile + "\";");
                out.write("\n");
                out.write("\tstatistics-file\t\"" + statisticFile + "\";");
                out.write("\n");
                out.write("\tmemstatistic-file\t\"" + memstatisticFile + "\";");
                out.write("\n");

                if (! forwarders.isEmpty()) {
                    out.write("\tforwarders\t" + forwarders);
                    out.write("\n");
                }

                out.write("\tnotify\t" + notify + ";");
                out.write("\n");

                out.write("};");
                out.write("\n\n");

                // write zone
                int len = TopDomains.size();
                String path = "";
                for (int idx = 0; idx <len; ++idx) {
                    // forward lookup zone
                    out.write("zone \"");
                    out.write(TopDomains.elementAt(idx).domainName);
                    out.write("\" in {");
                    out.write("\n");
                    out.write("\ttype\tmaster;\n");

                    path = directory + "/data/zone file/" +
                            TopDomains.elementAt(idx).domainName + "zone";
                    out.write("\tfile\t\"" + path + "\";\n");
                    out.write("};");
                    out.write("\n\n");

//                    writeForwardZoneFile(path, TopDomains.elementAt(idx));
                    writeForwardZoneFile(
                            TopDomains.elementAt(idx).domainName + "zone",
                            TopDomains.elementAt(idx));

                    // reverse lookup zone
                    String str = searchReverseZone(TopDomains.elementAt(idx).domainName);
                    out.write("zone \"");
                    out.write(str);
                    out.write("\" in {\n");
                    out.write("\ttype\tmaster;\n");
                    out.write("\tfile\t\"" + directory + "/data/zone file/" +
                            str + ".zone\"\n");
                    out.write("};\n");
                    out.write("\n");

                    writeReverseZoneFile(str + ".zone", TopDomains.elementAt(idx));
                }

                // close stream
                out.close();

                // Nếu có output
                if (!this.filePathResultOutput.isEmpty()) {
//                    String etc = filePathResultOutput + "/etc";
//                    this.runShellCommand("mkdir " + etc);
//                    this.runShellCommand("copy named.conf " + etc);
//
//                    String command = "copy *.zone " + filePathResultOutput;
//                    this.runShellCommand(command);
                } else {
//                    this.runShellCommand("cp named.conf /etc/ -f");
//                    this.runShellCommand("mkdir " + directory + "/data");
//                    this.runShellCommand("cp *.zone " + directory + "/data");
                }

                JOptionPane.showMessageDialog(this.pane, "Convert successful!");
            } else {
                JOptionPane.showMessageDialog(
                        this.pane,
                        "This function is still running on Linux!");
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }

    public String runShellCommand (String Command) {
        String res = "";
        String lsString = null;
        Process process = null;
        
        try {
            process = Runtime.getRuntime().exec(Command);
            BufferedReader bufferedReader = new
            BufferedReader(new InputStreamReader(process.getInputStream()));
            
            while ((lsString = bufferedReader.readLine()) != null) {
                System.out.println(lsString);
                res += lsString +"\n";
            }
            
            try {
                process.waitFor();
            } catch (InterruptedException e) {
                //e.printStackTrace();
                System.err.println (e);
            }
        } catch (IOException e) {
            //e.printStackTrace();
            System.err.println (e);
        }
        
        return res;
    }

    public void writeForwardZoneFile (String path, Domain zone) {
        try {
            FileWriter fstream = new FileWriter(path);
            BufferedWriter out = new BufferedWriter(fstream);

            out.write("$TTL\t" + convertTTL(zone.nameServer.getTTL()) + "\n");
            out.write("@\tIN\tSOA\t" + zone.nameServer.getHostName() +
                    " " + zone.nameServer.getRoot() + " (\n");
            out.write("\t\t\t" + zone.nameServer.getSerial() + "; serial\n");
            out.write("\t\t\t" + zone.nameServer.getRefeshTime() + "; refesh time\n");
            out.write("\t\t\t" + zone.nameServer.getReplyTime() + "; retry\n");
            out.write("\t\t\t" + zone.nameServer.getExpireTime() + "; expire\n");
            out.write("\t\t\t" + zone.nameServer.getMinimumTime() + "; minimum\n");
            out.write(")\n");


            for (int idx = 0; idx < zone.Hosts.size(); ++ idx) {
                if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.NS)) {
                    out.write("\tIN\tNS\t" + zone.Hosts.elementAt(idx).getHostName() + "\n");
                } else if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.MX)) {
                    out.write(
                            "\tIN\tMX\t" +
                            zone.Hosts.elementAt(idx).getOther() + "\t" +
                            zone.Hosts.elementAt(idx).getHostName() + "\n");
                } else if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.A)) {
                    out.write(
                            zone.Hosts.elementAt(idx).getHostName() + "\t" +
                            "IN\tA\t" +
                            zone.Hosts.elementAt(idx).getAddress() + "\n");
                } else if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.CNAME)) {
                    out.write(
                            zone.Hosts.elementAt(idx).getHostName() + "\t" +
                            "IN\tCNAME\t" +
                            zone.Hosts.elementAt(idx).getAddress() + "\n");
                }
            }

            // nếu như domain có đường mạng con
            String delegate = "";
            for (int idx = 0; idx < zone.subDomains.size(); ++ idx) {
                if (isDelegated(zone.subDomains.elementAt(idx))) {
                    String []delegateServer = getServer(
                            zone.subDomains.elementAt(idx).fileNS,
                            zone.domainName);
                    delegate += ";delegate \n";
                    delegate += zone.subDomains.elementAt(idx).Folder +
                            "\tIN\tNS\t" + delegateServer [0] + "\n";
                    delegate += delegateServer [2] + "\tIN\tA\t" + delegateServer [1] + "\n";
                    delegate += "\n";
                } else {
                    String output = subDomain(zone.subDomains.elementAt(idx), zone.domainName);
                    out.write(output);
                }
            }
            out.write("\n");
            out.write(delegate);

            out.close();

        } catch (IOException e) {
            System.err.println (e);
        }
    }

    public String convertTTL (String TTL) {
        // $TTL 0:1:0:0 ;DDDD:HH.MM.SS
        // In linux: $TTL 3600       ; 1 hour

        int old = 0;
        int index = 0;
        String []str = new String [4];
        for (int idx = 0; idx < TTL.length(); ++ idx) {
            if (TTL.charAt(idx) == ':') {
                str [index] = TTL.substring(old, idx);
                old = idx + 1;
                index ++;
            }
        }
        str [index] = TTL.substring(old, TTL.length());

        int second = 0;
        String comment = "";
        if (! str [0].equals("0")) {
            comment += str [0] + " day(s), ";
            second += Integer.parseInt(str [0]) *86400; // 1 day = 86400 seconds
        }

        if (! str [1].equals("0")) {
            comment += str [1] + " hour(s), ";
            second += Integer.parseInt(str [1]) *3600; // 1 hour = 3600 seconds
        }

        if (! str [2].equals("0")) {
            comment += str [2] + " minute(s), ";
            second += Integer.parseInt(str [2]) *60; // 1 minute = 60 seconds
        }

        if (! str [3].equals("0")) {
            comment += str [3] + " second(s)";
            second += Integer.parseInt(str [3]); 
        }

        String newTTL = Integer.toString(second) + ";\t" + comment;
        
        return newTTL;
    }

    public String subDomain (Domain zone, String domain) {
        String output = "";
        
        if (zone.subDomains.isEmpty()) {
            String sub = getSubDomain(domain, zone.domainName);

//            output += sub;
//            output += "\tIN\tA\t";
//            String str [] = getServer (zone.fileNS, domain);
//            output += str [1] + "\n";

            output += "\n";
            for (int idx = 0; idx < zone.Hosts.size(); ++idx) {
                output += zone.Hosts.elementAt(idx).getHostName() + "." + sub;
                output += "\tIN\t" + zone.Hosts.elementAt(idx).getHostType() + "\t";
                output += zone.Hosts.elementAt(idx).getAddress() + "." + sub + "\n";
            }
        } else {
            for (int idx = 0; idx < zone.subDomains.size(); ++idx) {
                output += subDomain (zone.subDomains.elementAt(idx), zone.Folder);
            }
        }

        return output;
    }

    public String getSubDomain (String domain, String str) {
        // domain = abc.com.
        // str = net1.abc.com

        int idx = str.indexOf(domain);
        return str.substring(0, idx -1);
    }

    public boolean isDelegated (Domain zone) {
        if (zone.nameServer.getHostName() == null) {
            return true;
        }

        return false;
    }

    public String [] getServer (String strNS, String zone) {
        // strNS = server1.net1.abc.com.[172.29.72.1]
        String delegate [] = new String [3];

        int idx = strNS.indexOf('[');
        delegate [0] = strNS.substring(0, idx);
        delegate [1] = strNS.substring(idx +1, strNS.indexOf(']'));

        idx = strNS.indexOf(zone);
        delegate [2] = strNS.substring(0, idx -1);

        return delegate;
    }

    public void writeReverseZoneFile (String path, Domain zone) {
        try {
            FileWriter fstream = new FileWriter(path);
            BufferedWriter out = new BufferedWriter(fstream);

            out.write("$TTL\t" + convertTTL(zone.nameServer.getTTL()) + "\n");
            out.write("@\tIN\tSOA\t" + zone.nameServer.getHostName() +
                    " " + zone.nameServer.getRoot() + " (\n");
            out.write("\t\t\t" + zone.nameServer.getSerial() + "; serial\n");
            out.write("\t\t\t" + zone.nameServer.getRefeshTime() + "; refesh time\n");
            out.write("\t\t\t" + zone.nameServer.getReplyTime() + "; retry\n");
            out.write("\t\t\t" + zone.nameServer.getExpireTime() + "; expire\n");
            out.write("\t\t\t" + zone.nameServer.getMinimumTime() + "; minimum\n");
            out.write(")\n");

            for (int idx = 0; idx < zone.Hosts.size(); ++ idx) {
                if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.NS)) {
                    out.write("\tIN\tNS\t" + zone.Hosts.elementAt(idx).getHostName() + "\n");
                }

                if (zone.Hosts.elementAt(idx).getHostType().equals(Host.TYPE_HOST.A)) {
                    out.write(
                            getHostAddress(zone.Hosts.elementAt(idx).getAddress()) +
                            "\tIN\tPTR\t" +
                            zone.Hosts.elementAt(idx).getHostName() + "." + zone.domainName);
                    out.write("\n");
                }
            }

            out.close();

        } catch (IOException e) {
            System.err.println (e);
        }
    }

    public String getHostAddress (String address) {
        // address = 192.168.1.1
        // return "1"
        int idx = address.lastIndexOf('.');
        return address.substring(idx +1);
    }

    public String getReverseZone (String str) {
        // str = xxx.xxx.xxx.x.Subnet
        String strReverse = "";
        String []arrReverse = new String[3];
        int len = str.length();
        int old = 0;
        int index = 0;
        for (int idx = 0; idx < len; ++idx) {
            if (str.charAt(idx) == '.') {
                arrReverse [index] = str.substring(old, idx);
                old = idx +1;
                index += 1;
            }
        }

        for (int idx = 2; idx >=0; --idx) {
            strReverse += arrReverse [idx];
            strReverse += ".";
        }
        strReverse += "in-addr.arpa";
        
        return strReverse;
    }

    public String searchReverseZone (String forwardZone) {
        int len = DNSConvert.TopDomains.size();
        String strReverseZone = "";
        for (int idx = 0; idx < len; ++idx) {
            String zone = this.forwardZone.elementAt(idx);
            if (zone.substring(1, zone.length()).equals(forwardZone.substring(0, forwardZone.length() -1))) {
                strReverseZone = getReverseZone(this.reverseZone.elementAt(idx));
                break;
            }
        }

        return strReverseZone;
    }
    
    public static String dectectOS () {
        String os = System.getProperty("os.name").toLowerCase();

        if (os.indexOf( "win" ) >= 0) {
            os = "Windows";
        } else if (os.indexOf( "mac" ) >= 0) {
            os = "Mac";
        } else if (os.indexOf( "nix") >=0 || os.indexOf( "nux") >=0) {
            os = "Unix";
        } else {
            os = "Your OS is not supported!";
        }

        return os;
    }
    
    public static Domain findDomain (Vector <Domain> parent, String domain) {
        Domain res = null;

        int len = parent.size();
        for (int idx = 0; idx < len; ++idx) {
            if (parent.elementAt(idx).Folder.equals(domain)) {
                res = parent.elementAt(idx);
                break;
            }

            if (parent.elementAt(idx).subDomains.size() >0) {
                res = findDomain (parent.elementAt(idx).subDomains, domain);
            }
        }

        return res;
    }

    public static Vector <Domain> getTopDomain () {
        return TopDomains;
    }

    public static void setDomain (
            Vector <Domain> parent, // top of all server
            String folder,          // folder name to set
            Domain domain) {        // domain want to set

        int len = parent.size();
        for (int idx = 0; idx < len; ++idx) {
            if (parent.elementAt(idx).Folder.equals(folder)) {
                parent.setElementAt(domain, idx);
                break;
            }

            if (parent.elementAt(idx).subDomains.size() >0) {
                setDomain (parent.elementAt(idx).subDomains, folder, domain);
            }
        }
    }

    private void clearTable() {
        //DefaultTableModel dm = (DefaultTableModel)table.getModel();
        int n = model.getRowCount();

        for(int i = 0; i < n; i++) {
            model.setValueAt("", i, 0);
            model.setValueAt("", i, 1);
            model.setValueAt("", i, 2);
        }
    }

    // tìm kiếm record forward nào đi với reverse nào
    private void searchDomains(
            Vector<String> ForwardZone,
            Vector<String> ReverseZone,
            String pathForwardZone, String pathReverseZone){
        
        String tmp = "";
        DomainInformation = new Vector<DomainInfo>();
        
        for(int i = 0; i < ForwardZone.size(); i++) {
            tmp = ForwardZone.elementAt(i);
            if(tmp.charAt(0) == '*') {
                DomainInfo df = new DomainInfo();
                df.setForwardZone(tmp.substring(1));
                Vector <String> list1 = FileAndFolder.list(pathForwardZone + "/" + df.getForwardZone() );

                int idx = JProcess.findStringIndex(list1, '[');
                String ip = JProcess.getStringBetween(list1.elementAt(idx), '[', ']');
                Vector <String>list2 = FileAndFolder.list(pathReverseZone);
                idx = findReverseZone(ip,list2);

                if (idx >= 0) {
                    df.setReverseZone(list2.elementAt(idx).substring(1));
                } else {
                    df.setReverseZone("none");
                }

                DomainInformation.add(df);
            }
        }
    }
    
    private void setComboBoxData(JComboBox combo, Vector<String> data) {
        combo.removeAllItems();
        for(int i = 0; i < data.size(); i++) {
            combo.insertItemAt(data.elementAt(i), i);
        }
    }
    
    private void setTableData() {
        for(int i = 0; i < DomainInformation.size(); i++) {
            if( i <= model.getColumnCount()) {
                model.setValueAt( String.valueOf(i + 1),i, 0);
                model.setValueAt( DomainInformation.elementAt(i).getForwardZone(),i, 1);
                model.setValueAt( DomainInformation.elementAt(i).getReverseZone(),i, 2);
            }
            else{
                model.insertRow( i, new Object[] {
                                        String.valueOf(i + 1),
                                        DomainInformation.elementAt(i).getForwardZone(),
                                        DomainInformation.elementAt(i).getReverseZone()});
            }
        }
    }

    private int findReverseZone(String ip, Vector<String>reverse) {
        int idx = ip.lastIndexOf('.');

        if(idx >=0) {
            ip = ip.substring(0, idx);
        }

        for(int i = 0; i < reverse.size(); i++) {
            if(reverse.elementAt(i).substring(1).startsWith(ip)) {
                return i;
            }
        }

        return -1;
    }

    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                           tree.getLastSelectedPathComponent();

        if (node == null) {
            return;
        }

        Object nodeInfo = node.getUserObject();
        String folder = (String) nodeInfo;
        Object path[] = node.getUserObjectPath();
        String tmp = "";

        if(path.length >= 2) {
            if (node.isLeaf()) {
                for(int i = 1; i < path.length; i++) {
                    tmp += (String)path[i];
                    tmp += '\\';
                }

                if(filePathNameServer == null) {
                    JOptionPane.showMessageDialog(pane, "Please input Folder.", "DNS Converter",0);
                    return;
                }

                Vector<String> lst = FileAndFolder.listFolder(filePathNameServer + "\\" + tmp);
                DefaultMutableTreeNode nodeTemp = null;
                
                for(int i = 0; i < lst.size(); i++) {
                    nodeTemp = new DefaultMutableTreeNode(lst.elementAt(i));
                    node.add(nodeTemp);
                }
            }

            String tmp2 = "";
            for(int i = 1; i < path.length; i++) {
                tmp2 += (String)path[i];
                tmp2 += '\\';
            }
            
            forwardZone = FileAndFolder.list(filePathNameServer + "\\" + tmp2);
            reverseZone = FileAndFolder.list(filePathReverseZone);

            searchDomains (
                    forwardZone,
                    reverseZone,
                    filePathNameServer + "\\" + tmp2,
                    filePathReverseZone);

            reverseZone = JProcess.removeCharBegin(reverseZone, 0);
            reverseZone.add("none");
            reverseZone.add(" ");
            clearTable();
            comboReverseZone.removeAllItems();
            setComboBoxData(comboReverseZone,reverseZone);
            setTableData();
        }
        
        if(path.length >= 3 ) {
            String tmp2 = "";
            String tmp3 = "";

            for(int i = 1; i < path.length; i++)
            {
                tmp2 += (String)path[i];
                tmp2 += '\\';
                
            }
            
            if (path [1].toString().equals("Forward Lookup Zone")) {
                for(int i = path.length - 1; i>=2 ;i--) {
                    tmp3 += (String)path[i];
                    tmp3 += '.';
                }
            }
            
            if(path[1].toString().equals("Reverse Lookup Zone")) {
               Vector<String> files = FileAndFolder.listFile (filePathNameServer + "\\" + tmp2);
               
               for(int i = 0; i < files.size(); i++) {
                   if(files.elementAt(i).endsWith("in-addr.arpa.dns")) {

                       tmp3 = files.elementAt(i);

                       int k = tmp3.lastIndexOf('.');
                       
                       if( k >= 0) {
                           tmp3 = tmp3.substring(0, k+1);
                       }
                   }
               }
            }

            try {
                //JOptionPane.showMessageDialog(paneCenter, filePathNameServer + "\\" + tmp2 + tmp3.substring(0, tmp3.length() -1 ) + ".dns" );
                textPreview.setText("");
                readDatabase(filePathNameServer + "\\" + tmp2 + tmp3.substring(0, tmp3.length() -1 ) + ".dns" );
            }catch (IOException ex) {
                JOptionPane.showMessageDialog(pane, ex.getMessage(), "DNS Converter",0);
            }

        }
    }

    private void readDatabase(String path) throws IOException {
        if(!path.isEmpty()) {
            BufferedReader br = new BufferedReader(new FileReader(path));

            String txt;
            while(true) {
                txt = br.readLine();
                if(txt == null) {
                    break;
                }

                if(txt.startsWith("(same as parent folder)")) {
                    int idx = txt.lastIndexOf('(');
                    if(idx >= 0) {
                        txt = txt.substring(idx);
                    }

                    txt = txt.replaceAll("\t", "  ");
                    txt = "- " + txt;
                    textPreview.append("\n");
                    textPreview.append(txt);
                }
            }

            br.close();
        }
    }

    private void loadDomains(){
        try {
            Vector<String> listFolder = FileAndFolder.listFolder(filePathForwardZone);
            TopDomains = new Vector<Domain>();
        
            for(int i = 0; i < listFolder.size(); i++) {
                Domain d = loadTopDomain(listFolder.elementAt(i),filePathForwardZone);
                TopDomains.add(d);
                TopDomains.elementAt(i).loadSubDomains();
            }
        }catch(Exception ex) {
            JOptionPane.showMessageDialog(paneCenter, ex.getMessage(), "DNS Converter - Error", 0);
        }

        JOptionPane.showMessageDialog(paneCenter, "Checking and Load all domains sucessful !", "DNS Converter - Message", 1);
    }

    private Domain loadTopDomain(String DomainName, String Path) {
        Domain d = new Domain();
        String fileNS = "";
        String fileDatabase="";
        String folder = "";
        Vector<Host> arrHost;
        NameServer nameServer;
        Vector<String> listFile = FileAndFolder.listFile(Path + "\\" + DomainName);
        
        if(listFile.size() <= 2) {
            for(int i = 0; i < listFile.size(); i++) {
                if(listFile.elementAt(i).startsWith(DomainName)) {
                    fileDatabase = listFile.elementAt(i);
                }

                int j = listFile.elementAt(i).indexOf('[');
                if (j >= 0) {
                    fileNS = listFile.elementAt(i);
                }
            }
        } else {
            JOptionPane.showMessageDialog(paneCenter, "File Structure invalid","DNS Converter",0);
            return null;
        }
        //load name server
        
        try {
            nameServer = new NameServer(
                    NameServer.TYPE_SERVER.PRIMARY,
                    Path + "\\" + DomainName + "\\" + fileNS
                    );
        
        //load host
            Host host = new Host();
            arrHost =  host.buildHost(Path + "\\" + DomainName + "\\" + fileDatabase);

            folder = DomainName;
            if(!DomainName.endsWith(".")) {
                DomainName += ".";
            }

            d = new Domain(
                    nameServer,
                    arrHost, DomainName, Path, fileDatabase, fileNS, folder);

        } catch (Exception e) {
            JOptionPane.showMessageDialog(paneCenter, e.getMessage(), "DNS Converter", 0);
        }

        return d;
    }

    public void createAndShowGUI() {
        //Make sure we have nice window decorations.
//        JFrame.setDefaultLookAndFeelDecorated(false);

        frame = new JFrame("DNS Converter");
//        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setContentPane(addComponentsToPane());
        
        frame.pack();
        frame.setVisible(true);
        frame.setSize(1024, 550);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
    }
}